package com.clinic.logic.user;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.clinic.accessor.db.PatientAccessor;
import com.clinic.accessor.db.UserContactAccessor;
import com.clinic.entity.db.Patient;
import com.clinic.entity.db.UserContact;
import com.clinic.entity.gui.GuiPagination;
import com.clinic.entity.gui.GuiPatient;
import com.clinic.entity.gui.GuiUserContact;
import com.clinic.entity.param.Index;
import com.clinic.util.CommonUtil;
import com.clinic.util.ConvertUtil;

@Component
public class PatientLogic {

	@Autowired
	private PatientAccessor patientAccessor;
	
	@Autowired
	private UserContactAccessor userContactAccessor;
	
	public GuiPatient insertPatient(GuiPatient guiPatient) {
		Patient patient = ConvertUtil.getPatientByGuiPatient(guiPatient, new Patient());
		Patient iPatient = patientAccessor.insertOrUpdate(patient);
		
		GuiUserContact guiContact = guiPatient.getContact();
		UserContact contact = ConvertUtil.getUserContactByGuiUserContact(guiContact, new UserContact());
		contact.setUser(iPatient);
		UserContact iContact = userContactAccessor.insertOrUpdate(contact);
		
		GuiPatient uPatient = ConvertUtil.getGuiPatientByPatient(iPatient);
		GuiUserContact uContact = ConvertUtil.getGuiUserContactByUserContact(iContact);
		uContact.setUser(uPatient);
		
		uPatient.setContact(uContact);
		
		return uPatient;
	}
	
	public GuiPatient updatePatient(GuiPatient guiPatient) {		

		Patient patient = patientAccessor.getPatientById(guiPatient.getUserId());
		Patient oPatient = ConvertUtil.getPatientByGuiPatient(guiPatient, patient);
		UserContact contact = patient.getContact();
		if(contact == null) {
			contact = new UserContact();
		}
		UserContact oContact = ConvertUtil.getUserContactByGuiUserContact(guiPatient.getContact(), contact);
		oContact.setUser(oPatient);
		oPatient.setContact(oContact);
		Patient uPatient = patientAccessor.insertOrUpdate(oPatient);
		
		GuiPatient result = ConvertUtil.getGuiPatientByPatient(uPatient);
		//result.setContact(ConvertUtil.getGuiUserContactByUserContact(uPatient.getContact()));
		return result;

	}
	
	@Transactional
	public GuiPatient getPatientDetailsById(long id) {
		Patient patient = patientAccessor.getPatientById(id);	
		GuiPatient result = ConvertUtil.getGuiPatientByPatient(patient);
		result.setContact(ConvertUtil.getGuiUserContactByUserContact(patient.getContact()));
		
		return result;
	}
	
	public boolean isValidPatientInsert(GuiPatient guiPatient) {
		
		return StringUtils.isBlank(guiPatient.getName()) ||
				(guiPatient != null && (guiPatient.getDob() != null));
	}
	
	public boolean isValidPatientUpdate(GuiPatient guiPatient) {
		
		long userId = guiPatient.getUserId();
		Patient result = patientAccessor.getPatientById(userId);
		return (result != null); // TODO find better validation process
	}
	
	public List<GuiPatient> getPatientList(Index index) {
		List<Patient> patientList = patientAccessor.getPatients(index);
		return getGuiPatientsByPatients(patientList);
	}
	
	public List<GuiPatient> getPatientListByTerm(String term, String column, Index index) {
		List<Patient> patientList = patientAccessor.getOrderedPatientsByTerm(term, column, index);		
		return getGuiPatientsByPatients(patientList);
	}
	
	public List<GuiPatient> getPatientsNotInIds(Set<Long> userIds, Index index){
		List<GuiPatient> result = new ArrayList<>();
		List<Patient> patients = patientAccessor.getPatientsNotInIds(userIds, index);
		for (Patient patient : patients) {
			result.add(ConvertUtil.getGuiPatientByPatient(patient));
		}
		return result;
	}
	
	public void deletePatientDetailsById(long id) {
		Patient patient = patientAccessor.getPatientById(id);
		if (patient != null) {
			// TODO delete other related data before ... appointments, contacts... etc
			patientAccessor.delete(patient);
		}
	}
	
	public GuiPagination getPaginationOfPatientsByTerm(String term, String column, int page) {
		int total = patientAccessor.countPatientsByTerm(term, column);
		return CommonUtil.getPaginationInfo(page, total);
	}
	
	public GuiPagination getPaginationOfPatients(int page) {
		int total = patientAccessor.countPatients();
		return CommonUtil.getPaginationInfo(page, total);
	}

	public GuiPagination getPaginationOfPatients(int page, int reduceCount) {
		int total = patientAccessor.countPatients();
		return CommonUtil.getPaginationInfo(page, total - reduceCount);
	}
	
	public List<GuiPatient> getPatients(Index index){
		List<GuiPatient> result = new ArrayList<>();
		List<Patient> patients = patientAccessor.getPatients(index);
		for (Patient patient : patients) {
			result.add(ConvertUtil.getGuiPatientByPatient(patient));
		}
		return result;
	}
	
	private List<GuiPatient> getGuiPatientsByPatients(List<Patient> patientList) {
		List<GuiPatient> result = new ArrayList<>();
		for (Patient patient : patientList) {
			result.add(ConvertUtil.getGuiPatientByPatient(patient));
		}
		return result;
	}

}


